# -*- coding: utf-8 -*-

# backtest.py


try:
    import Queue as queue
except ImportError:
    import queue


class Backtest(object):
    """
    这个类封装了进行事件驱动回测的设置与组成
    """

    def __init__(self, data_handler, execution_handler, portfolio, strategy):

        # 数据处理类
        self.data_handler_cls = data_handler
        # 策略处理类--->生成signal
        self.strategy_cls = strategy
        # 接收signal  处理订单及头寸
        self.portfolio_cls = portfolio
        # 去除order 进行模拟交易
        self.execution_handler_cls = execution_handler


        # 信号
        self.signals = 0
        # 订单
        self.orders = 0
        # 交易
        self.fills = 0
        #
        self.num_strats = 1

    def _generate_trading_instances(self, stock_code, start_date, initial_capital=10000):
        """
        从不同的类类型中生成交易实例对象  （初始化）
        """
        print(
            "Creating DataHandler,Strategy,Portfolio and ExecutionHandler"
        )
        self.data_handler = self.data_handler_cls(stock_code)
        self.strategy = self.strategy_cls(self.data_handler.stock_data)
        self.portfolio = self.portfolio_cls(self.data_handler, self.events, start_date, initial_capital)
        self.execution_handler = self.execution_handler_cls(self.events)

    def _run_backtest(self):
        """
        执行回测
        """

        while True:
            try:
                event = self.events.get(False)
            except queue.Empty:
                break
            else:
                if event is not None:
                    if event.type == 'MARKET':
                        self.strategy.calculate_signals(event)
                        self.portfolio.update_timeindex(event)
                    elif event.type == 'SIGNAL':
                        self.signals += 1
                        self.portfolio.update_signal(event)
                    elif event.type == 'ORDER':
                        self.orders += 1
                        self.execution_handler.execute_order(event)
                    elif event.type == 'FILL':
                        self.fills += 1
                        self.portfolio.update_fill(event)

    def _output_performance(self):
        """
        输出回测得到策略业绩结果
        """
        self.portfolio.create_equity_curve_dateframe()

        print("Creating summary stats...")
        stats = self.portfolio.output_summary_stats()

        print("Creating equity curve...")
        print(self.portfolio.equity_curve.tail(10))

        print("Signals: %s" % self.signals)
        print("Orders: %s" % self.orders)
        print("Fills: %s" % self.fills)

    def simulate_trading(self, stock_code, start_date):
        """
        模拟回测以及输出业绩结果的过程
        """
        # out = open("opt.csv", "w")
        self._generate_trading_instances(stock_code, start_date)
        self._run_backtest()
        stats = self._output_performance()

        # tot_ret = float(stats[0][1].replace("%", ""))
        # sharpe = float(stats[1][1])
        # max_dd = float(stats[2][1].replace("%", ""))
        # dd_dur = int(stats[3][1])

        # out.write(
        #     "%s,%s,%s,%s,%s,%s,%s\n" %
        #     sp["ols_window"], sp["zscore_high"], sp["zscore_low"],
        #     tot_ret, sharpe, max_dd, dd_dur
        # )
        # out.close()
